home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / lib / awf / pass1 < prev    next >
Text File  |  1995-05-16  |  9KB  |  213 lines

  1. # first pass:  macro expansion and .if
  2. # We support macros, conditionals (of three quite limited forms), and macro
  3. # argument substitution.
  4. BEGIN {
  5.        curmacro = ""
  6.        macros[""] = 0          # just to make it an array
  7.        macrolen[""] = 0        # just to make it an array
  8.        macrotext[0] = ""       # just to make it an array
  9.        args[""] = ""           # just to make it an array
  10.        ntext = 1               # first slot in macrotext; cannot be 0
  11.        nroffset = 0            # offset between NR and "real" line numbers
  12.        inname = "?"            # input filename
  13.        sp = 0                  # stack "pointer" (number of stacked macros)
  14.        maxsp = 25              # limit on nesting depth
  15.        macrostack[sp] = ""     # to make it an array
  16.        nleftstack[sp] = ""     # to make it an array
  17.        ptrstack[sp] = ""       # to make it an array
  18.        nargstack[sp] = ""      # to make it an array
  19.        argstack[sp] = ""       # to make it an array
  20.        condstack[sp] = ""      # to make it an array
  21. }
  22. /^\.\^#/ {                     # filename and line no of next line: .^# no fn
  23.        nroffset = (NR+1) - $2
  24.        inname = $3
  25.        print
  26.        next
  27. }
  28. /^\.de/ {                      # macro start
  29.        curmacro = "." $2
  30.        macros[curmacro] = ntext
  31.        macrostart = ntext
  32.        next
  33. }
  34. curmacro != "" && $0 !~ /^\.\.$/ {     # macro text - \\ becomes \
  35.        if ($0 !~ /\\/)         # quick case, no backslashes
  36.                line = $0
  37.        else {
  38.                line = ""
  39.                for (n = 1; n <= length; n++) {
  40.                        if (substr($0, n, 2) == "\\\\")
  41.                                n++
  42.                        line = line substr($0, n, 1)
  43.                }
  44.        }
  45.        macrotext[ntext++] = line
  46.        next
  47. }
  48. curmacro != "" && $0 ~ /^\.\.$/ {      # macro end
  49.        macrolen[curmacro] = ntext - macrostart
  50.        curmacro = ""
  51.        print ".^#", NR - nroffset + 1, inname
  52.        next
  53. }
  54. $0 ~ /^\./ && ( macros[$1] != 0 || $0 ~ /^\.(i[ef]|el)/ ) {
  55.        # something that needs attention
  56.        print ".^=", NR - nroffset, inname
  57.        line = $0
  58.        nleft = 0
  59.        macro = "<none>"
  60.        nargs = 0
  61.  
  62.        while (line != "") {
  63.                # conditionals; note that 1-n is !n (awk doesn't have !)
  64.                invert = 0
  65.                if (line ~ /^\.i[ef] !/)
  66.                        invert = 1
  67.                prevcond = cond
  68.                cond = 0
  69.                if (line !~ /^\.(i[ef]|el)/) {          # not conditional
  70.                        cond = 1
  71.                        iflen = 0
  72.                } else if (line ~ /^\.i[ef] !?\\n\(\.\$[<=>][0-9] /) {
  73.                        # arithmetic comparison on arg count
  74.                        iflen = length(".if .n(.$=x ") + invert
  75.                        n = substr(line, iflen-1, 1) + 0
  76.                        op = substr(line, iflen-2, 1)
  77.                        if (op == "=" && nargs == n)
  78.                                cond = 1
  79.                        else if (op == "<" && nargs < n)
  80.                                cond = 1
  81.                        else if (op == ">" && nargs > n)
  82.                                cond = 1
  83.                } else if (line ~ /^\.i[ef] !?'\\\$[0-9]'[^']*' /) {
  84.                        # string equality on argument
  85.                        iflen = length(".if '.$n'") + invert
  86.                        n = substr(line, iflen-1, 1)+0
  87.                        if (n <= nargs)
  88.                                s1 = args[n]
  89.                        else
  90.                                s1 = ""
  91.                        i = index(substr(line, iflen+1), "'")
  92.                        s2 = substr(line, iflen+1, i-1)
  93.                        iflen += i+1
  94.                        if (s1 == s2)
  95.                                cond = 1
  96.                } else if (line ~ /^\.i[ef] !?[nt] /) {
  97.                        # nroff vs troff
  98.                        iflen = length(".if n ") + invert
  99.                        if (substr(line, iflen-1, 1) == "n")
  100.                                cond = 1
  101.                } else if (line ~ /^\.el /) {
  102.                        cond = 1 - prevcond
  103.                        iflen = length(".el ")
  104.                } else {
  105.                        line = ".tm unknown .if/.ie form: " line
  106.                        cond = 1
  107.                        iflen = 0
  108.                }
  109.                if (invert)
  110.                        cond = 1 - cond
  111.                if (cond && iflen > 0)          # trim true conditional off
  112.                        line = substr(line, iflen+1)
  113.  
  114.                # do argument substitution, if necessary
  115.                if (cond && line ~ /\\\$/) {
  116.                        orig = line
  117.                        line = ""
  118.                        for (pos = index(orig, "\\$"); pos > 0; \
  119.                                                pos = index(orig, "\\$")) {
  120.                                if (pos > 1)
  121.                                        line = line substr(orig, 1, pos-1)
  122.                                c = substr(orig, pos+2, 1)
  123.                                if (c ~ /[0-9]/ && c+0 <= nargs)
  124.                                        line = line args[c+0]
  125.                                orig = substr(orig, pos+3)
  126.                        }
  127.                        line = line orig        # the remnant
  128.                }
  129.  
  130.                # is it an nroff command?
  131.                if (cond && line ~ /^\./) {
  132.                        cmd = substr(line, 1, 3)
  133.                        while (cmd ~ / $/)
  134.                                cmd = substr(cmd, 1, length(cmd)-1)
  135.                } else
  136.                        cmd = ""
  137.  
  138.                # deal with it
  139.                if (!cond)
  140.                        nop = 0         # nothing
  141.                else if (cmd == "" || macros[cmd] == 0)
  142.                        print line      # not a nested macro
  143.                else if (sp >= maxsp)
  144.                        print ".tm macros nested too deeply (" sp " levels)"
  145.                else {                  # nesting
  146.                        # stack old one
  147.                        sp++
  148.                        nleftstack[sp] = nleft
  149.                        ptrstack[sp] = ptr
  150.                        macrostack[sp] = macro
  151.                        nargstack[sp] = nargs
  152.                        condstack[sp] = cond
  153.                        for (i = 1; i <= nargs; i++)
  154.                                argstack[sp ":" i] = args[i]
  155.  
  156.                        # start new one, mostly pulling arguments apart
  157.                        macro = cmd
  158.                        nleft = macrolen[macro]
  159.                        ptr = macros[macro]
  160.                        cond = 0
  161.                        argno = 1
  162.                        pos = length(macro) + 1
  163.                        for (;;) {
  164.                                while (substr(line, pos, 1) ~ /[ \t]/)
  165.                                        pos++
  166.                                if (pos > length(line))
  167.                                        break           # NOTE BREAK OUT
  168.                                arg = ""
  169.                                if (substr(line, pos, 1) == "\"") {
  170.                                        pos++
  171.                                        while (substr(line, pos, 1) ~ /[^"]/) {
  172.                                                arg = arg substr(line, pos, 1)
  173.                                                pos++
  174.                                        }
  175.                                        pos++
  176.                                } else
  177.                                        while (substr(line, pos, 1) ~ /[^ \t]/) {
  178.                                                arg = arg substr(line, pos, 1)
  179.                                                pos++
  180.                                        }
  181.                                args[argno++] = arg
  182.                        }
  183.                        nargs = argno - 1
  184.                }
  185.  
  186.                # clean up any completed macros
  187.                while (nleft <= 0 && sp > 0) {
  188.                        nleft = nleftstack[sp]
  189.                        ptr = ptrstack[sp]
  190.                        macro = macrostack[sp]
  191.                        nargs = nargstack[sp]
  192.                        cond = condstack[sp]
  193.                        for (i = 1; i <= nargs; i++)
  194.                                args[i] = argstack[sp ":" i]
  195.                        sp--
  196.                }
  197.  
  198.                # finally, get next line
  199.                if (nleft > 0) {
  200.                        line = macrotext[ptr++]
  201.                        nleft--
  202.                } else
  203.                        line = ""       # signal loop to terminate
  204.        }
  205.  
  206.        print ".^#", NR - nroffset + 1, inname
  207.        next
  208. }
  209. {
  210.        # it's ordinary
  211.        print
  212. }
  213.